/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { Dimensions, PixelRatio } from 'react-native';
import { Avoid } from '@hadss/react_native_avoid_area';
import { AvoidArea, AvoidAreaType } from '@hadss/react_native_avoid_area/src/turbo/NativeAvoidModule';

interface AvoidAreaContextType {
  topRectHeight: number;
  bottomRectHeight: number;
  orientation: string;
  cutoutMargin: number;
  isWideDevice: boolean;
  isHighDevice: boolean;
  isStoreNeedAvoid: boolean;
  isWideCutout: boolean;
}

const AvoidAreaContext = createContext<AvoidAreaContextType | undefined>(undefined);

interface AvoidAreaProviderProps {
  children: ReactNode;
}

export const AvoidAreaProvider: React.FC<AvoidAreaProviderProps> = ({ children }) => {
  const [topRectHeight, setTopRectHeight] = useState(0);
  const [bottomRectHeight, setBottomRectHeight] = useState(0);
  const [orientation, setOrientation] = useState<string>('');
  const [cutoutMargin, setCutoutMargin] = useState(0);
  const [isWideDevice, setIsWideDevice] = useState(false);
  const [isHighDevice, setIsHighDevice] = useState(false);
  const [isStoreNeedAvoid, setIsStoreNeedAvoid] = useState(false);
  const [isWideCutout, setIsWideCutout] = useState(false);

  const pixelRatio = PixelRatio.get() ? PixelRatio.get() : 1;

  const handleTopArea = (avoidArea: AvoidArea, windowWidth: number): void => {
    let cutoutAtMiddle = avoidArea.topRect.left / pixelRatio < windowWidth / 2;
    if (cutoutAtMiddle || !avoidArea.topRect.left) {
      setIsWideCutout(avoidArea.topRect.width > 100);
      setOrientation('topRectMiddle');
      setCutoutMargin(0);
    } else {
      setOrientation('topRect');
      let margin = windowWidth - avoidArea.topRect.left / pixelRatio;
      setCutoutMargin(margin);
    }
  };
  const handleLeftArea = (avoidArea: AvoidArea, windowHeight: number): void => {
    let cutoutAtMiddle = avoidArea.leftRect.top / pixelRatio < windowHeight / 2 && avoidArea.leftRect.top / pixelRatio > windowHeight / 4;
    if (cutoutAtMiddle || !avoidArea.leftRect.top) {
      setOrientation('leftRectMiddle');
    } else {
      setOrientation('leftRect');
    }
    let margin = (avoidArea.leftRect.width + avoidArea.leftRect.left) / pixelRatio;
    setCutoutMargin(margin);
  };
  const handleBottomArea = (avoidArea: AvoidArea, windowWidth: number, windowHeight: number): void => {
    let cutoutAtMiddle = avoidArea.bottomRect.left / pixelRatio > windowWidth / 4;
    if (cutoutAtMiddle || !avoidArea.bottomRect.left) {
      setIsStoreNeedAvoid(true);
      setOrientation('bottomRectMiddle');
      let margin = windowHeight - avoidArea.bottomRect.top / pixelRatio;
      let height = avoidArea.bottomRect.height / pixelRatio;
      setCutoutMargin(margin + height);
    } else {
      setOrientation('bottomRect');
      let margin = (avoidArea.bottomRect.width + avoidArea.bottomRect.left) / pixelRatio;
      setCutoutMargin(margin);
    }
  };
  const handleRightArea = (avoidArea: AvoidArea, windowWidth: number, windowHeight: number): void => {
    let cutoutAtMiddle = avoidArea.rightRect.top / pixelRatio < windowHeight / 2;
    if (cutoutAtMiddle || !avoidArea.rightRect.top) {
      setOrientation('rightRectMiddle');
    } else {
      setOrientation('rightRect');
    }
    let margin = windowWidth - avoidArea.rightRect.left / pixelRatio;
    setCutoutMargin(margin);
  };
  const calcCutoutAvoidArea = (avoidArea: AvoidArea): void => {
    const windowWidth = Dimensions.get('window').width;
    const windowHeight = Dimensions.get('window').height;
    const wideScreen = 600;
    setIsStoreNeedAvoid(false);
    setIsWideDevice(windowWidth > wideScreen);
    setIsHighDevice(windowHeight > wideScreen);
    setCutoutMargin(0);
    setIsWideCutout(false);
    if (avoidArea.topRect.height) {
      handleTopArea(avoidArea, windowWidth);
    } else if (avoidArea.leftRect.height) {
      handleLeftArea(avoidArea, windowHeight);
    } else if (avoidArea.bottomRect.height) {
      handleBottomArea(avoidArea, windowWidth, windowHeight);
    } else if (avoidArea.rightRect.height) {
      handleRightArea(avoidArea, windowWidth, windowHeight);
    } else {
      setOrientation('');
      setCutoutMargin(0);
    }
  };

  const initAvoidArea = (): void => {
    // 状态栏
    let type = AvoidAreaType.TYPE_SYSTEM;
    let avoidArea = Avoid.getWindowAvoidArea(type);
    let topHeight = avoidArea.topRect.height / pixelRatio;
    setTopRectHeight(topHeight);

    // 导航条
    type = AvoidAreaType.TYPE_NAVIGATION_INDICATOR;
    avoidArea = Avoid.getWindowAvoidArea(type);
    let bottomHeight = avoidArea.bottomRect.height / pixelRatio;
    setBottomRectHeight(bottomHeight);

    // 刘海屏
    type = AvoidAreaType.TYPE_CUTOUT;
    avoidArea = Avoid.getWindowAvoidArea(type);
    calcCutoutAvoidArea(avoidArea);
  };

  useEffect(() => {
    //初始化时获取区域避让数据
    initAvoidArea();
    //监听区域避让数据变化S
    Avoid.addAvoidAreaListener((data): void => {
      if (data.type === AvoidAreaType.TYPE_SYSTEM) {
        // 状态栏
        let type = AvoidAreaType.TYPE_SYSTEM;
        let avoidArea = Avoid.getWindowAvoidArea(type);
        let topHeight = avoidArea.topRect.height / pixelRatio;
        setTopRectHeight(topHeight);
      } else if (data.type === AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
        // 导航条
        let type = AvoidAreaType.TYPE_NAVIGATION_INDICATOR;
        let avoidArea = Avoid.getWindowAvoidArea(type);
        let bottomHeight = avoidArea.bottomRect.height / pixelRatio;
        setBottomRectHeight(bottomHeight);
      } else if (data.type === AvoidAreaType.TYPE_CUTOUT) {
        calcCutoutAvoidArea(data.area);
      }
    });

    return (): void => {
      Avoid.removeAvoidAreaListener();
    };
  }, []);

  const contextValue: AvoidAreaContextType = {
    topRectHeight,
    bottomRectHeight,
    orientation,
    cutoutMargin,
    isWideDevice,
    isHighDevice,
    isStoreNeedAvoid,
    isWideCutout,
  };

  return <AvoidAreaContext.Provider value={contextValue}>{children}</AvoidAreaContext.Provider>;
};

export const useAvoidArea = (): AvoidAreaContextType => {
  const context = useContext(AvoidAreaContext);
  if (context === undefined) {
    throw new Error('useAvoidArea must be used within an AvoidAreaProvider');
  }
  return context;
};
